﻿#include "ICPIO.h"

#include <windows.h>

ICPService* ICPIO::_service = NULL;
ICPIO::ICPIO(ICPService* service) { _service = service; }

ICPIO::~ICPIO() {}

void ICPIO::readInput() {
    readParamDate();
    readParamRule();
    readParamModel();
    readParamKpi();
    readRuleOnOff();
    readRuleCCAR5();

    readBaseList();
    readFleetList();
    readAirportList();
    readPairingConfigList();
    readResLimitList();
    readAirportBreakList();
    readAirportTransferList();
    readAirportNightList();
    readAirportConfigList();
    readBaseOverstaffList();
    readBaseDirectList();
    readPatternList();
    readDutyRatioList();
    readPairingRatioList();
    readHrCrew();
    readTechInfo();
    readPersonSchedule();
    readSchLegList();
    if (!ICPUtility::isDebug) {
        readPrevUnClosedPairingList();
        readDeadHeadGrdList();
        readDeadHeadElfList();
        readDeadHeadAirList();
    }
    readBestAirlineList();
    readSchConfigB();

    // 剔除机场表中没用到的机场
    vector<BasAirport*> airports = _service->getAirportList();
    for (int i = 0; i < airports.size(); i++) {
        bool isFound = false;
        for (auto it : _service->getLegList()) {
            if (it->getDep() == airports[i]) {
                isFound = true;
                break;
            } else if (it->getArr() == airports[i]) {
                isFound = true;
                break;
            }
        }
        if (!isFound) {
            delete airports[i];
            airports.erase(airports.begin() + i);
            i--;
        }
    }
    // for (int i = 0; i < airports.size(); i++)
    //{
    //	airports[i]->print();
    // }
    _service->setAirportList(airports);

    // 无效的资源约束去掉
    // for (int i = 0; i < ICPUtility::basResLimitList.size(); i++)
    //{
    //	auto bgnTerminal =
    //_service->getAirport(ICPUtility::basResLimitList[i]->getBgnTerminal());
    // auto endTerminal =
    //_service->getAirport(ICPUtility::basResLimitList[i]->getEndTerminal());
    // if (bgnTerminal == NULL || endTerminal == NULL)
    //	{
    //		delete ICPUtility::basResLimitList[i];
    //		ICPUtility::basResLimitList.erase(ICPUtility::basResLimitList.begin()
    //+ i); 		i--;
    //	}
    // }

    cout << "pairingConfigList: " << ICPUtility::pairingConfigList.size() << endl;
    cout << "reslimit: " << ICPUtility::basResLimitList.size() << endl;
    cout << "airport: " << _service->getAirportList().size() << endl;
    cout << "flight: " << _service->getLegList().size() << endl;

    cout << "bgnDate: " << getTimeStr(ICPUtility::bgnDate) << endl;
    cout << "endDate: " << getTimeStr(ICPUtility::endDate) << endl;
    // cout << "bgnTime: " << getTimeStr(ICPUtility::bgnTime) << endl;
    // cout << "endTime: " << getTimeStr(ICPUtility::endTime) << endl;
    // cout << "dummyBgnDate: " << getTimeStr(ICPUtility::dummyBgnDate) << endl;
    // cout << "dummyEndDate: " << getTimeStr(ICPUtility::dummyEndDate) << endl;
}

void ICPIO::readParamDate() {
    string fileName = ICPUtility::INPUTPATH + string("param_date.csv");
    cout << "readParamDate from file " << fileName << "！" << endl;
    ifstream file(fileName.c_str());
    if (!file) {
        cout << "file " << fileName << " does not exist！" << endl;
        exit(0);
    }

    string buf;
    while (getline(file, buf)) {
        if (isUtf8(buf)) {
            buf = Utf8ToAnsi(buf);
        }
        vector<string> subStrs = splitString(buf.c_str(), ",");
        if (subStrs.size() < 2) {
            continue;
        }

        string name = subStrs[0];
        string val = subStrs[1].c_str();
        if (name == "BgnDate") {
            ICPUtility::bgnDate = convertToDate(val);
        } else if (name == "EndDate") {
            ICPUtility::endDate = convertToDate(val) + DAY_SECONED_DEFINE; // 故意往后多排一天
        } else if (name == "ModuleFlag") {
            ICPUtility::moduleFlag = val;
        } else if (name == "Filiales") {
            ICPUtility::filiale = val;
        }
    }
    file.close();

    ICPUtility::bgnTime = ICPUtility::bgnDate;
    ICPUtility::endTime = ICPUtility::endDate + DAY_SECONED_DEFINE - 1;

    ICPUtility::dummyBgnDate =
        ICPUtility::bgnDate - ICPUtility::maxDaysInPairing * DAY_SECONED_DEFINE + DAY_SECONED_DEFINE;
    ICPUtility::dummyEndDate =
        ICPUtility::endDate + ICPUtility::maxDaysInPairing * DAY_SECONED_DEFINE - DAY_SECONED_DEFINE;

    cout << "StartDate is " << getTimeStr(ICPUtility::bgnDate) << endl;
    cout << "EndDate is " << getTimeStr(ICPUtility::endDate) << endl;
}

void ICPIO::readParamRule() {
    string fileName = ICPUtility::INPUTPATH + string("param_rule.csv");
    cout << "readParam121 from file " << fileName << "！" << endl;
    ifstream file(fileName.c_str());
    if (!file) {
        cout << "file " << fileName << " does not exist！" << endl;
        exit(0);
    }
    string buf;
    bool firstLine = true;
    while (getline(file, buf)) {
        if (firstLine) {
            firstLine = false;
            continue;
        }
        if (isUtf8(buf)) {
            buf = Utf8ToAnsi(buf);
        }

        vector<string> subStrs = splitString(buf.c_str(), ",");
        if (subStrs.size() < 2) {
            continue;
        }

        string name = subStrs[0];
        double val = atoi(subStrs[1].c_str());
        if (name == "SIGN_IN") // 签入时间
        {
            ICPUtility::signIn = val * 60;
        } else if (name == "SIGN_OUT") // 签出时间
        {
            ICPUtility::signOut = val * 60;
        } else if (name == "BREAK_INTERVAL") // 二次进场标准
        {
            ICPUtility::breakInterval = val * 60;
        } else if (name == "TRANSFER_INTERVAL") // 换机间隔判断标准
        {
            ICPUtility::minTransferInterval = val * 60;
        } else if (name ==
                   "LAYOVER_BUFFER") // 隔日休息时间裕度值（标准休息时间是10小时，裕度是在10小时基础上增加的部分）
        {
            ICPUtility::minRestInterval = 10 * HOUR_SECONED_DEFINE + val * 60;
        } else if (name == "MAX_LEG_NUM_IN_DUTY") // 执勤期内最大航段数
        {
            ICPUtility::maxLegNumInDuty = val;
        } else if (name == "MAX_FLYTIME_IN_DUTY") // 执勤期内最大分钟
        {
            ICPUtility::maxFlyTime = val * 60;
        } else if (
            name ==
            "DAY5_BUFFER") // 连续飞行不超5天裕度（注：第4天不能超过20:00,否则执行阶段稍有延误，会出现连续飞行5天）
        {
            ICPUtility::day5Buffer = val * 60;
        } else if (name == "MAX_BASE_CNT") // 一个任务环最多包含多少个基地
        {
            ICPUtility::maxBaseCnt = val;
        }
    }

    file.close();
    if (ICPUtility::isDebug) {
        cout << "ICPUtility::signIn = " << ICPUtility::signIn << endl;
        cout << "ICPUtility::signOut = " << ICPUtility::signOut << endl;
        cout << "ICPUtility::breakInterval = " << ICPUtility::breakInterval << endl;
        cout << "ICPUtility::minTransferInterval = " << ICPUtility::minTransferInterval << endl;
        cout << "ICPUtility::minRestInterval = " << ICPUtility::minRestInterval << endl;
    }
}

void ICPIO::readParamModel() // 算法模型参数
{
    string fileName = ICPUtility::INPUTPATH + string("param_model.csv");
    cout << "readParamModel from file " << fileName << "！" << endl;
    ifstream file(fileName.c_str());
    if (!file) {
        cout << "file " << fileName << " does not exist！" << endl;
        exit(0);
    }
    string buf;
    bool firstLine = true;
    while (getline(file, buf)) {
        if (firstLine) {
            firstLine = false;
            continue;
        }
        if (isUtf8(buf)) {
            buf = Utf8ToAnsi(buf);
        }

        vector<string> subStrs = splitString(buf.c_str(), ",");
        if (subStrs.size() < 2) {
            continue;
        }

        string name = subStrs[0];
        string val = subStrs[1];
        if (name == "EXP_MODEL_YN") {
            ICPUtility::isExpModel = atoi(val.c_str());
        } else if (name == "GAP") {
            ICPUtility::gap = atof(val.c_str());
        } else if (name == "FIX_UB_BAR") {
            ICPUtility::fixUbBar = atof(val.c_str());
        } else if (name == "FIX_LB_BAR") {
            ICPUtility::fixLbBar = atof(val.c_str());
        } else if (name == "MIN_BETTER_COLS") {
            ICPUtility::minBetterCols = atoi(val.c_str());
        } else if (name == "SLOW_IMPROVE_ITER") {
            ICPUtility::slowImproveIter = atoi(val.c_str());
        } else if (name == "DOMINATE_BAR") {
            ICPUtility::dominateBar = atoi(val.c_str());
        }
    }
    file.close();

    if (ICPUtility::isDebug) {
        cout << "gap is " << ICPUtility::gap << endl;
        cout << "fixUbBar is " << ICPUtility::fixUbBar << endl;
        cout << "fixLbBar is " << ICPUtility::fixLbBar << endl;
        cout << "minBetterCols is " << ICPUtility::minBetterCols << endl;
        cout << "slowImproveIter is " << ICPUtility::slowImproveIter << endl;
        cout << "dominateBar is " << ICPUtility::dominateBar << endl;
    }
}

void ICPIO::readParamKpi() {
    string fileName = ICPUtility::INPUTPATH + string("param_kpi.csv");
    cout << "readParamKpi from file " << fileName << "！" << endl;
    ifstream file(fileName.c_str());
    if (!file) {
        cout << "file " << fileName << " does not exist！" << endl;
        exit(0);
    }

    string buf;
    bool firstLine = true;
    while (getline(file, buf)) {
        if (firstLine) {
            firstLine = false;
            continue;
        }
        if (isUtf8(buf)) {
            buf = Utf8ToAnsi(buf);
        }

        vector<string> subStrs = splitString(buf.c_str(), ",");
        if (subStrs.size() < 2) {
            continue;
        }

        string name = subStrs[0];
        double val = atoi(subStrs[1].c_str());
        if (name == "costCover") // 航班覆盖
        {
            ICPUtility::costCover = val;
        } else if (name == "costDeadheadVA") // 坐机
        {
            ICPUtility::costDeadheadVA = val;
        } else if (name == "costDeadheadVB") // 坐车
        {
            ICPUtility::costDeadheadVB = val;
        } else if (name == "costPerCrewPerDay") // 人天成本
        {
            ICPUtility::costPerCrewPerDay = val;
        } else if (name == "costDutyMornEven") // 早晚班
        {
            ICPUtility::costDutyMornEven = val;
        } else if (name == "costDutyMorning") // 早班
        {
            ICPUtility::costDutyMorning = val;
        } else if (name == "costDutyEvening") // 晚班
        {
            ICPUtility::costDutyEvening = val;
        } else if (name == "costLayoverDays") // 过夜天数
        {
            ICPUtility::costLayoverDays = val;
        } else if (name == "costBreak") // 二次进场次数
        {
            ICPUtility::costBreak = val;
        } else if (name == "costBreakLeg4") // 单日飞4段且需要二次进场
        {
            ICPUtility::costBreakLeg4 = val;
        } else if (name == "costBreakMulti") // 单日多个二次进场
        {
            ICPUtility::costBreakMulti = val;
        } else if (name == "costBreakShort") // 二次进退场休息时间小于1小时成本
        {
            ICPUtility::costBreakShort = val;
        } else if (name == "costFreeOneDay") // 外站空一天
        {
            ICPUtility::costFreeOneDay = val;
        } else if (name == "costFreeTwoDay") // 外站空2天
        {
            ICPUtility::costFreeTwoDay = val;
        } else if (name == "costLayoverAirport") // 排班周期内的不同过夜站点的个数超过2（不含）成本
        {
            ICPUtility::costLayoverAirport = val;
        } else if (name == "costLayoverHome") // 过家门而不入
        {
            ICPUtility::costLayoverAirport = val;
        } else if (name == "costLayoverNonBase") // 非基地过夜
        {
            ICPUtility::costLayoverNonBase = val;
        } else if (name == "costThinTask") // 瘦班成本
        {
            ICPUtility::costThinTask = val;
        } else if (name == "costDutyTransfer") // 同日换飞机
        {
            ICPUtility::costDutyTransfer = val;
        } else if (name == "costVoyageOrderly") // 任务环稳定性越低，扣分越多
        {
            ICPUtility::costVoyageOrderly = val;
        } else if (name == "costExcessCrew") // 超额成本
        {
            ICPUtility::costExcessCrew = val;
        } else if (name == "profitMatchPattern") // 模板匹配收益
        {
            ICPUtility::profitMatchPattern = val;
        } else if (name == "profitHisRatio") // 与历史拟合程度越高，加分越多
        {
            ICPUtility::profitHisRatio = val;
        } else if (name == "profitRoundTrip") // 同一天经停或来回程组在一起
        {
            ICPUtility::profitRoundTrip = val;
        } else if (name == "costUnclosed") // 未闭环罚分
        {
            ICPUtility::costUnclosed = val;
        } else if (name == "costDP") // 战场时间越短越好
        {
            ICPUtility::costDP = val;
        }
    }

    file.close();

    if (ICPUtility::isDebug) {
        cout << "ICPUtility::costCover = " << ICPUtility::costCover << endl;
        cout << "ICPUtility::costDeadheadVA = " << ICPUtility::costDeadheadVA << endl;
        cout << "ICPUtility::costDeadheadVB = " << ICPUtility::costDeadheadVB << endl;
        cout << "ICPUtility::costPerCrewPerDay = " << ICPUtility::costPerCrewPerDay << endl;
        cout << "ICPUtility::costDutyMornEven = " << ICPUtility::costDutyMornEven << endl;
        cout << "ICPUtility::costDutyMorning = " << ICPUtility::costDutyMorning << endl;
        cout << "ICPUtility::costDutyEvening = " << ICPUtility::costDutyEvening << endl;
        cout << "ICPUtility::costLayoverDays = " << ICPUtility::costLayoverDays << endl;
        cout << "ICPUtility::costBreak = " << ICPUtility::costBreak << endl;
        cout << "ICPUtility::costBreakLeg4 = " << ICPUtility::costBreakLeg4 << endl;
        cout << "ICPUtility::costBreakShort = " << ICPUtility::costBreakShort << endl;
        cout << "ICPUtility::costFreeOneDay = " << ICPUtility::costFreeOneDay << endl;
        cout << "ICPUtility::costFreeTwoDay = " << ICPUtility::costFreeTwoDay << endl;
        cout << "ICPUtility::costLayoverAirport = " << ICPUtility::costLayoverAirport << endl;
    }
}

void ICPIO::readRuleOnOff() {
    vector<string> lstRuleOn;
    string fileName = ICPUtility::INPUTPATH + string("rule_onoff.csv");
    cout << "readRuleOnOff from file " << fileName << "！" << endl;
    ifstream file(fileName.c_str());
    if (!file) {
        cout << "file " << fileName << " does not exist！" << endl;
        exit(0);
    }
    string buf;
    bool firstLine = true;
    while (getline(file, buf)) {
        if (firstLine) {
            firstLine = false;
            continue;
        }
        if (isUtf8(buf)) {
            buf = Utf8ToAnsi(buf);
        }

        // FUN_CODE,RULE_NAME
        vector<string> subStrs = splitString(buf.c_str(), ",");
        if (subStrs.size() < 2) {
            continue;
        }

        string ruleNo = subStrs[0];
        lstRuleOn.push_back(ruleNo);
    }

    file.close();

    fileName = ICPUtility::INPUTPATH + string("rule_name_map.csv");
    cout << "readRuleNameMap from file " << fileName << "！" << endl;
    ifstream file1(fileName.c_str());
    if (!file1) {
        cout << "file " << fileName << " does not exist！" << endl;
        exit(0);
    }

    ICPUtility::setRule.clear();
    firstLine = true;
    while (getline(file1, buf)) {
        if (firstLine) {
            firstLine = false;
            continue;
        }
        if (isUtf8(buf)) {
            buf = Utf8ToAnsi(buf);
        }

        // ISP_CODE,FUN_CODE,EXIST_YN
        vector<string> subStrs = splitString(buf.c_str(), ",");
        if (subStrs.size() < 3) {
            continue;
        }

        string ispCode = subStrs[0];
        string funCode = subStrs[1];
        bool isExists = subStrs[2] == "Y"; // ISP的规则是否在ICREW系统有注册，有注册的要看是否要验证，没注册的一定要验证
        if (!isExists) {
            ICPUtility::setRule.insert(ispCode);
        } else {
            if (find(lstRuleOn.begin(), lstRuleOn.end(), funCode) != lstRuleOn.end()) {
                ICPUtility::setRule.insert(ispCode);
            }
        }
    }

    file1.close();

    for (auto it : ICPUtility::setRule) {
        if (ICPUtility::isDebug) {
            cout << "rule " << it << " is "
                 << "on" << endl;
        }
    }
}

void ICPIO::readRuleCCAR5() // R5标准
{
    string fileName = ICPUtility::INPUTPATH + string("rule_ccar5.csv");
    cout << "readRuleCCAR5 from file " << fileName << "！" << endl;
    ifstream file(fileName.c_str());
    if (!file) {
        cout << "file " << fileName << " does not exist！" << endl;
        exit(0);
    }
    string buf;
    bool firstLine = true;
    while (getline(file, buf)) {
        if (firstLine) {
            firstLine = false;
            continue;
        }
        if (isUtf8(buf)) {
            buf = Utf8ToAnsi(buf);
        }
        /*
        0-PRI,
        1-CREW_ID,
        2-CREW_NUM,
        3-FLIGHT_COM,
        4-FLIGHT_CODE,
        5-AC_TYPES,
        6-AC_REGS,
        7-AIRPORTS,
        8-DUTY_HOURS_MIN,
        9-DUTY_HOURS_MAX,
        10-D_OR_I
        */

        vector<string> subStrs = splitString(buf.c_str(), ",");
        if (subStrs.size() < 11) {
            continue;
        }

        CCAR5 ccar5;
        ccar5.pri = atoi(subStrs[0].c_str());
        ccar5.crewId = atoi(subStrs[1].c_str());
        ccar5.crewNum = atoi(subStrs[2].c_str());
        ccar5.flightCom = subStrs[3];
        ccar5.flightCode = subStrs[4];
        ccar5.acTypes = subStrs[5];
        ccar5.acRegs = subStrs[6];
        ccar5.airports = subStrs[7];
        ccar5.minFdp = subStrs[8].empty() ? 0 : atoi(subStrs[8].c_str()) * 60;
        ccar5.maxFdp = subStrs[9].empty() ? 999999 : atoi(subStrs[9].c_str()) * 60;
        ccar5.maxFdp = ccar5.maxFdp <= ccar5.minFdp ? 999999 : ccar5.maxFdp;
        ccar5.dori = subStrs[10] == "I" ? D_OR_I::I : D_OR_I::D;
        ICPUtility::ccar5List.push_back(ccar5);
    }
    file.close();

    std::sort(ICPUtility::ccar5List.begin(), ICPUtility::ccar5List.end(), comCCAR5ByPri);
    for (auto it : ICPUtility::ccar5List) {
        if (ICPUtility::isDebug) {
            cout << " pri = " << it.pri << " crewId = " << it.crewId << " crewNum = " << it.crewNum
                 << " flightCom = " << it.flightCom << " flightCode = " << it.flightCode << " acTypes = " << it.acTypes
                 << " acRegs = " << it.acRegs << " airports = " << it.airports << " minFdp = " << it.minFdp
                 << " maxFdp = " << it.maxFdp << " dori = " << it.dori << endl;
        }
    }
}

void ICPIO::readFleetList() {
    string buf;
    string fileName = ICPUtility::INPUTPATH + string("Fleet.csv");
    cout << "readFleetList from file " << fileName << "！" << endl;
    ifstream file(fileName.c_str());
    if (!file) {
        cout << "file " << fileName << " does not exist！" << endl;
        exit(0);
    }
    bool firstLine = true;
    while (getline(file, buf)) {
        if (firstLine) {
            firstLine = false;
            continue;
        }
        if (isUtf8(buf)) {
            buf = Utf8ToAnsi(buf);
        }

        /*0机型，1-机型组*/
        vector<string> subStrs = splitString(buf.c_str(), ",");
        if (subStrs.size() < 2) {
            continue;
        }

        string acType = subStrs[0];
        string acTypeCrew = subStrs[1];

        BasFleet* fleet = new BasFleet(acType, acTypeCrew);
        _service->setFleetMap(acType, fleet);
    }

    file.close();
}

void ICPIO::readAirportList() {
    vector<BasAirport*> airportList;
    string buf;
    string fileName = ICPUtility::INPUTPATH + string("airport.csv");
    cout << "readAirportList from file " << fileName << "！" << endl;
    ifstream file(fileName.c_str());
    if (!file) {
        cout << "file " << fileName << " does not exist！" << endl;
        exit(0);
    }
    bool firstLine = true;
    while (getline(file, buf)) {
        if (firstLine) {
            firstLine = false;
            continue;
        }
        if (isUtf8(buf)) {
            buf = Utf8ToAnsi(buf);
        }

        /*0-机场三字码，1-国内国际,2-特殊机场等级,3-时区*/
        vector<string> subStrs = splitString(buf.c_str(), ",");
        if (subStrs.size() < 4) {
            continue;
        }

        string code3 = subStrs[0];
        string doriStr = subStrs[1];
        D_OR_I dori = D_OR_I::D;
        if (doriStr == "D") {
            dori = D_OR_I::D;
        } else if (doriStr == "I") {
            dori = D_OR_I::I;
        } else if (doriStr == "R") {
            dori = D_OR_I::R;
        } else if (doriStr == "T") {
            dori = D_OR_I::T;
        } else {
            cout << "Error: IO::readAirport. Cannot find airport dori " << doriStr << endl;
            exit(0);
        }
        // 特殊机场等级
        SP_LEVEL spLevel = SP_LEVEL::SP_LEVEL_NIL;
        if (subStrs[2] == "1") {
            spLevel = SP_LEVEL::SP_LEVEL_1;
        } else if (subStrs[2] == "2") {
            spLevel = SP_LEVEL::SP_LEVEL_2;
        }
        // 时区
        int zoneTime = 480 * 60;
        if (!subStrs[3].empty()) {
            zoneTime = atoi(subStrs[3].c_str()) * 60;
        }

        BasAirport* airport = new BasAirport(code3, dori, spLevel, zoneTime);
        if (find(ICPUtility::basBaseStrList.begin(), ICPUtility::basBaseStrList.end(), code3) !=
            ICPUtility::basBaseStrList.end()) {
            airport->setIsBase(true);
        }
        airportList.push_back(airport);
    }
    _service->setAirportList(airportList);

    file.close();
}

void ICPIO::readBaseList() {
    ICPUtility::basBaseStrList.clear();
    string buf;
    string fileName = ICPUtility::INPUTPATH + string("base.csv");
    cout << "readBaseList from file " << fileName << "！" << endl;
    ifstream file(fileName.c_str());
    if (!file) {
        cout << "file " << fileName << " does not exist！" << endl;
        exit(0);
    }
    bool firstLine = true;
    while (getline(file, buf)) {
        if (firstLine) {
            firstLine = false;
            continue;
        }
        if (isUtf8(buf)) {
            buf = Utf8ToAnsi(buf);
        }

        /*0-基地编码*/
        vector<string> subStrs = splitString(buf.c_str(), ",");
        if (subStrs.size() < 1) {
            continue;
        }
        string baseCode = subStrs[0]; // 基地编码
        ICPUtility::basBaseStrList.push_back(baseCode);
    }
    file.close();
}

void ICPIO::readPairingConfigList() {
    ICPUtility::pairingConfigList.clear();

    string buf;
    string fileName = ICPUtility::INPUTPATH + string("pairing_config.csv");
    cout << "readPairingConfigList from file " << fileName << "！" << endl;
    ifstream file(fileName.c_str());
    if (!file) {
        cout << "file " << fileName << " does not exist！" << endl;
        exit(0);
    }
    bool firstLine = true;
    while (getline(file, buf)) {
        if (firstLine) {
            firstLine = false;
            continue;
        }
        if (isUtf8(buf)) {
            buf = Utf8ToAnsi(buf);
        }

        /*0-机型组,
         * 1-基地，2-任务环首站,3-任务环未站,4-任务环最大天数国内,5-国际任务环最大天数*/
        vector<string> subStrs = splitString(buf.c_str(), ",");
        if (subStrs.size() < 6) {
            continue;
        }
        string acTypeCrew = subStrs[0];                 // 机型组
        string baseCode = subStrs[1];                   // 基地
        string bgnTerminal = subStrs[2];                // 任务环首站
        string endTerminal = subStrs[3];                // 任务环未站
        int maxPairingDays = atoi(subStrs[4].c_str());  // 国内任务环最大天数
        int maxPairingDaysI = atoi(subStrs[5].c_str()); // 国际任务环最大天数
        ICPPairingConfig* pairingConfig =
            new ICPPairingConfig(acTypeCrew, baseCode, bgnTerminal, endTerminal, maxPairingDays, maxPairingDaysI);
        ICPUtility::pairingConfigList.push_back(pairingConfig);
    }
    file.close();
}

void ICPIO::readResLimitList() {
    ICPUtility::basResLimitList.clear();

    string buf;
    string fileName = ICPUtility::INPUTPATH + string("res_limit.csv");
    cout << "readResLimitList from file " << fileName << "！" << endl;
    ifstream file(fileName.c_str());
    if (!file) {
        cout << "file " << fileName << " does not exist！" << endl;
        exit(0);
    }
    bool firstLine = true;
    while (getline(file, buf)) {
        if (firstLine) {
            firstLine = false;
            continue;
        }
        if (isUtf8(buf)) {
            buf = Utf8ToAnsi(buf);
        }

        /*0-日期，1-机型组,
         * 2-任务环首站,3-任务环未站,4-日飞行小时限制,5-日任务环数量限制,6-日国际班数量限制*/
        vector<string> subStrs = splitString(buf.c_str(), ",");
        if (subStrs.size() < 7) {
            continue;
        }
        time_t flightDate = convertToDate(subStrs[0]);  // 日期
        string acTypeCrew = subStrs[1];                 // 机型组
        string bgnTerminal = subStrs[2];                // 任务环首站
        string endTerminal = subStrs[3];                // 任务环未站
        double dailyFlyTime = atoi(subStrs[4].c_str()); // 日飞行时间限制（单位是小时）
        int dailyCnt = atoi(subStrs[5].c_str());        // 日任务环数量限制
        int dailyIRCnt = atoi(subStrs[6].c_str());      // 日国际任务环数量限制
        BasResLimit* basResLimit = new BasResLimit(flightDate, bgnTerminal, acTypeCrew, dailyCnt);
        ICPUtility::basResLimitList.push_back(basResLimit);
    }
    file.close();
}

void ICPIO::readAirportBreakList() {
    string buf;
    string fileName = ICPUtility::INPUTPATH + string("airport_break.csv");
    cout << "readAirportBreakList from file " << fileName << "！" << endl;
    ifstream file(fileName.c_str());
    if (!file) {
        cout << "file " << fileName << " does not exist！" << endl;
        exit(0);
    }
    bool firstLine = true;
    while (getline(file, buf)) {
        if (firstLine) {
            firstLine = false;
            continue;
        }
        if (isUtf8(buf)) {
            buf = Utf8ToAnsi(buf);
        }

        vector<string> subStrs = splitString(buf.c_str(), ",");
        if (subStrs.size() < 4)
            continue;

        BasAirport* airport = _service->getAirport(subStrs[0]);
        if (airport == NULL) {
            // cout << "Error: ICPIO::readBasAirportBreak. Cannot find airport " <<
            // subStrs[0] << endl;
            continue;
        }
        time_t breakInterval = atoi(subStrs[1].c_str()) * 60;
        time_t signIn = atoi(subStrs[2].c_str()) * 60;
        time_t signOut = atoi(subStrs[3].c_str()) * 60;
        BasAirportBreak* basAirportBreak = new BasAirportBreak(breakInterval, signIn, signOut);
        airport->setBasAirportBreak(basAirportBreak);
    }

    file.close();
}

void ICPIO::readAirportTransferList() {
    string buf;
    string fileName = ICPUtility::INPUTPATH + string("airport_transfer.csv");
    cout << "readAirportTransferList from file " << fileName << "！" << endl;
    ifstream file(fileName.c_str());
    if (!file) {
        cout << "file " << fileName << " does not exist！" << endl;
        exit(0);
    }
    bool firstLine = true;
    while (getline(file, buf)) {
        if (firstLine) {
            firstLine = false;
            continue;
        }
        if (isUtf8(buf)) {
            buf = Utf8ToAnsi(buf);
        }

        vector<string> subStrs = splitString(buf.c_str(), ",");
        if (subStrs.size() < 4)
            continue;

        BasAirport* airport = _service->getAirport(subStrs[0]);
        if (airport == NULL)
            continue;
        time_t sameInterval = atoi(subStrs[1].c_str()) * 60;
        time_t diffInterval = atoi(subStrs[2].c_str()) * 60;
        time_t ddInterval = atoi(subStrs[3].c_str()) * 60;
        BasAirportTransfer* basAirportTransfer = new BasAirportTransfer(sameInterval, diffInterval, ddInterval);
        airport->setBasAirportTransfer(basAirportTransfer);
    }

    file.close();
}

void ICPIO::readAirportNightList() {
    string buf;
    string fileName = ICPUtility::INPUTPATH + string("airport_night.csv");
    cout << "readAirportNightList from file " << fileName << "！" << endl;
    ifstream file(fileName.c_str());
    if (!file) {
        cout << "file " << fileName << " does not exist！" << endl;
        exit(0);
    }

    bool firstLine = true;
    while (getline(file, buf)) {
        if (firstLine) {
            firstLine = false;
            continue;
        }
        if (isUtf8(buf)) {
            buf = Utf8ToAnsi(buf);
        }

        vector<string> subStrs = splitString(buf.c_str(), ",");
        if (subStrs.size() < 13) {
            continue;
        }

        BasAirport* airport = _service->getAirport(subStrs[0]);
        if (airport == NULL) {
            // cout << "Error: ICPIO::readAirportNightList. Cannot find airport " <<
            // subStrs[0] << endl;
            continue;
        }
        time_t signIn = subStrs[1].empty() ? ICPUtility::signIn : atoi(subStrs[1].c_str()) * 60;   // 签入时长
        time_t signOut = subStrs[2].empty() ? ICPUtility::signOut : atoi(subStrs[2].c_str()) * 60; // 签出时长
        time_t signInDH = subStrs[3].empty() ? ICPUtility::signIn : atoi(subStrs[3].c_str()) * 60; // 置位签入时长
        time_t signOutDH = subStrs[4].empty() ? ICPUtility::signOut : atoi(subStrs[4].c_str()) * 60; // 置位签出时长
        time_t homeStd =
            subStrs[5].empty() ? ICPUtility::signIn : atoi(subStrs[5].c_str()) * 60; // 从家到航班起飞的时长
        time_t staHome =
            subStrs[6].empty() ? ICPUtility::signOut : atoi(subStrs[6].c_str()) * 60; // 从航班落地到家的时长
        time_t hotelStd =
            subStrs[7].empty() ? ICPUtility::signIn : atoi(subStrs[7].c_str()) * 60; // 从宾馆到航班起飞的时长
        time_t staHotel =
            subStrs[8].empty() ? ICPUtility::signOut : atoi(subStrs[8].c_str()) * 60; // 从航班落地到宾馆的时长
        time_t homeStdDH =
            subStrs[9].empty() ? ICPUtility::signIn : atoi(subStrs[9].c_str()) * 60; // 从家到置位航班起飞的时长
        time_t staHomeDH =
            subStrs[10].empty() ? ICPUtility::signOut : atoi(subStrs[10].c_str()) * 60; // 从置位航班落地到家的时长
        time_t hotelStdDH =
            subStrs[11].empty() ? ICPUtility::signIn : atoi(subStrs[11].c_str()) * 60; // 从宾馆到置位航班起飞的时长
        time_t staHotelDH =
            subStrs[12].empty() ? ICPUtility::signOut : atoi(subStrs[12].c_str()) * 60; // 从置位航班落地到宾馆的时长
        BasAirportNight* basAirportNight =
            new BasAirportNight(signIn, signOut, signInDH, signOutDH, homeStd, staHome, hotelStd, staHotel, homeStdDH,
                                staHomeDH, hotelStdDH, staHotelDH);
        airport->setBasAirportNight(basAirportNight);
    }

    file.close();
}

void ICPIO::readAirportConfigList() {
    string buf;
    string fileName = ICPUtility::INPUTPATH + string("airport_config.csv");
    cout << "readAirportConfigList from file " << fileName << "！" << endl;
    ifstream file(fileName.c_str());
    if (!file) {
        cout << "file " << fileName << " does not exist！" << endl;
        exit(0);
    }
    bool firstLine = true;
    ICPUtility::mapAirportConfig.clear();
    while (getline(file, buf)) {
        if (firstLine) {
            firstLine = false;
            continue;
        }
        if (isUtf8(buf)) {
            buf = Utf8ToAnsi(buf);
        }

        /*AC_TYPE_CREW,
        DEPARTURE_AIRPORT,
        ARRIVAL_AIRPORT,
        SIGN_IN_TIME,
        EXIT_TIME,
        PREVIOUS_RIDE_TIME,
        REAR_RIDE_TIME
        */
        vector<string> subStrs = splitString(buf.c_str(), ",");
        if (subStrs.size() < 7) {
            continue;
        }

        string acTypeCrew = subStrs[0];
        string dep = subStrs[1];
        if (_service->getAirport(dep) == NULL)
            continue;
        string arr = subStrs[2];
        time_t signIn = atoi(subStrs[3].c_str()) * 60;
        time_t signout = atoi(subStrs[4].c_str()) * 60;
        time_t drivingIn = atoi(subStrs[5].c_str()) * 60;
        time_t drivingOut = atoi(subStrs[6].c_str()) * 60;
        string key = acTypeCrew + dep + arr;
        AirportConfig airportConfig;
        airportConfig.acTypeCrew = acTypeCrew;
        airportConfig.dep = dep;
        airportConfig.arr = arr;
        airportConfig.signIn = signIn;
        airportConfig.signout = signout;
        airportConfig.drivingIn = drivingIn;
        airportConfig.drivingOut = drivingOut;

        ICPUtility::mapAirportConfig[key] = airportConfig;
    }
    file.close();
}

void ICPIO::readBaseOverstaffList() {
    string buf;
    string fileName = ICPUtility::INPUTPATH + string("base_overstaff.csv");
    cout << "readBaseOverstaffList from file " << fileName << "！" << endl;
    ifstream file(fileName.c_str());
    if (!file) {
        cout << "file " << fileName << " does not exist！" << endl;
        exit(0);
    }
    bool firstLine = true;
    ICPUtility::mapBaseOverstaff.clear();
    while (getline(file, buf)) {
        if (firstLine) {
            firstLine = false;
            continue;
        }
        if (isUtf8(buf)) {
            buf = Utf8ToAnsi(buf);
        }

        /*AC_TYPE_CREW,BASE,WEIGHT*/
        vector<string> subStrs = splitString(buf.c_str(), ",");
        if (subStrs.size() < 3)
            continue;

        string acTypeCrew = subStrs[0].empty() ? "ALL" : subStrs[0];
        string base = subStrs[1];
        double tightness = atoi(subStrs[2].c_str());
        string key = acTypeCrew + "-" + base;
        ICPUtility::mapBaseOverstaff[key] = tightness;
    }
    file.close();
}

void ICPIO::readBaseDirectList() {
    string buf;
    string fileName = ICPUtility::INPUTPATH + string("base_direct.csv");
    cout << "readBaseDirectList from file " << fileName << "！" << endl;
    ifstream file(fileName.c_str());
    if (!file) {
        cout << "file " << fileName << " does not exist！" << endl;
        exit(0);
    }
    bool firstLine = true;
    while (getline(file, buf)) {
        if (firstLine) {
            firstLine = false;
            continue;
        }
        if (isUtf8(buf)) {
            buf = Utf8ToAnsi(buf);
        }
        vector<string> subStrs = splitString(buf.c_str(), ",");
        if (subStrs.size() < 5) {
            continue;
        }

        baseDirect basedirect;
        basedirect.acTypes = subStrs[0];
        basedirect.base = subStrs[1];
        basedirect.include_airport_list = subStrs[2];
        basedirect.exclude_airport_list = subStrs[3];
        basedirect.fen = atof(subStrs[4].c_str());
        ICPUtility::lstBaseDirect.push_back(basedirect);
    }

    file.close();
}

void ICPIO::readPatternList() {
    string buf;
    string fileName = ICPUtility::INPUTPATH + string("icp_pattern.csv");
    cout << "readPatternList from file " << fileName << "！" << endl;
    ifstream file(fileName.c_str());
    if (!file) {
        cout << "file " << fileName << " does not exist！" << endl;
        exit(0);
    }

    bool firstLine = true;
    while (getline(file, buf)) {
        if (firstLine) {
            firstLine = false;
            continue;
        }
        if (buf.find("--") != string::npos)
            break;
        if (isUtf8(buf)) {
            buf = Utf8ToAnsi(buf);
        }
        vector<string> subStrs = splitString(buf.c_str(), ",");
        if (subStrs.size() < 10) {
            continue;
        }

        time_t bgnDate = subStrs[0].empty() ? convertToDate("2001-01-01") : convertToDate(subStrs[0]);
        time_t endDate = subStrs[1].empty() ? convertToDate("2050-12-31") : convertToDate(subStrs[1]);
        // 开始时间大于结束时间的，舍去
        if (bgnDate > endDate)
            continue;
        // 模板与自动范围不在一个区间的，舍去
        if (!isTimeConflict(bgnDate, endDate, ICPUtility::bgnDate - 4 * DAY_SECONED_DEFINE,
                            ICPUtility::endDate + 4 * DAY_SECONED_DEFINE)) {
            continue;
        }
        string weeks = subStrs[2];
        string t0 = ConvertPatternToVoyage(subStrs[3]);
        string t1 = ConvertPatternToVoyage(subStrs[4]);
        string t2 = ConvertPatternToVoyage(subStrs[5]);
        string t3 = ConvertPatternToVoyage(subStrs[6]);
        string t4 = ConvertPatternToVoyage(subStrs[7]);
        string t5 = ConvertPatternToVoyage(subStrs[8]);
        string t6 = ConvertPatternToVoyage(subStrs[9]);
        string voyage;
        if (t0.empty())
            continue;
        voyage = "/0" + t0;
        if (!t1.empty()) {
            voyage += "/1" + t1;
        }
        if (!t2.empty()) {
            voyage += "/2" + t2;
        }
        if (!t3.empty()) {
            voyage += "/3" + t3;
        }
        if (!t4.empty()) {
            voyage += "/4" + t4;
        }
        if (!t5.empty()) {
            voyage += "/5" + t5;
        }
        if (!t6.empty()) {
            voyage += "/6" + t6;
        }
        voyage += "/";
        BasPattern* basPattern = new BasPattern(bgnDate, endDate, weeks, voyage);
        ICPUtility::lstPattern.push_back(basPattern);
    }

    file.close();

    for (int i = 0; i < ICPUtility::lstPattern.size(); i++) {
        if (ICPUtility::isDebug) {
            ICPUtility::lstPattern[i]->print();
        }
    }
}

void ICPIO::readDutyRatioList() {
    string buf;
    string fileName = ICPUtility::INPUTPATH + string("duty_ratio.csv");
    cout << "readDutyRatioList from file " << fileName << "！" << endl;
    ifstream file(fileName.c_str());
    if (!file) {
        cout << "file " << fileName << " does not exist！" << endl;
        exit(0);
    }
    bool firstLine = true;
    while (getline(file, buf)) {
        if (firstLine) {
            firstLine = false;
            continue;
        }
        if (isUtf8(buf)) {
            buf = Utf8ToAnsi(buf);
        }
        vector<string> subStrs = splitString(buf.c_str(), ",");
        if (subStrs.size() < 2) {
            continue;
        }

        string voyage = subStrs[0];
        auto lst = splitString(voyage, "/");
        // 航站不衔接的不处理
        bool isConnect = true;
        for (size_t i = 1; i < lst.size(); i++) {
            if (lst[i - 1].substr(lst[i - 1].length() - 3) != lst[i].substr(lst[i].length() - 6, 3)) {
                isConnect = false;
                break;
            }
        }
        if (!isConnect) {
            continue;
        }

        // 统一思想：duty与duty之间用"/"，同一duty内部的leg之间用"-"
        replace(voyage.begin(), voyage.end(), '/', '-');
        double ratio = atof(subStrs[1].c_str());
        ICPUtility::mapDutyRatio[voyage] = ratio;
    }
    file.close();

    // 历史上航班衔接的拟合度
    ICPUtility::mapLinkRatio.clear();
    for (auto iter : ICPUtility::mapDutyRatio) {
        auto fltInfos = splitString(iter.first, "-");
        for (size_t i = 1; i < fltInfos.size(); i++) {
            string link = fltInfos[i - 1] + "-" + fltInfos[i];
            if (ICPUtility::mapLinkRatio.count(link) > 0) {
                ICPUtility::mapLinkRatio[link] = min(1, ICPUtility::mapLinkRatio[link] + iter.second);
            } else {
                ICPUtility::mapLinkRatio[link] = min(1, iter.second);
            }
        }
    }
}

void ICPIO::readPairingRatioList() {
    string buf;
    string fileName = ICPUtility::INPUTPATH + string("pairing_ratio.csv");
    cout << "readPairingRatioList from file " << fileName << "！" << endl;
    ifstream file(fileName.c_str());
    if (!file) {
        cout << "file " << fileName << " does not exist！" << endl;
        exit(0);
    }
    bool firstLine = true;
    while (getline(file, buf)) {
        if (firstLine) {
            firstLine = false;
            continue;
        }
        if (isUtf8(buf)) {
            buf = Utf8ToAnsi(buf);
        }
        vector<string> subStrs = splitString(buf.c_str(), ",");
        if (subStrs.size() < 2) {
            continue;
        }

        vector<string> lstDutyVoyage;
        vector<string> lstPairingVoyage;
        string flightVoyage = subStrs[0];
        double ratio = atof(subStrs[1].c_str());
        auto lst = splitString(flightVoyage, "/");
        // 未闭环的不处理
        string pairingDep = lst.front().substr(lst.front().length() - 6, 3);
        string pairingArr = lst.back().substr(lst.back().length() - 3, 3);
        if (pairingDep != pairingArr) {
            continue;
        }
        // 航站不衔接的不处理
        bool isConnect = true;
        for (size_t i = 1; i < lst.size(); i++) {
            if (lst[i - 1].substr(lst[i - 1].length() - 3) != lst[i].substr(lst[i].length() - 6, 3)) {
                isConnect = false;
                break;
            }
        }
        if (!isConnect) {
            continue;
        }
        // 修正任务环最大环长的定义标准（历史上超过最大定义值的，以历史记录为准）
        if (isStringNumeric(lst.back().substr(0, 1))) {
            int pairingDays = atoi(lst.back().substr(0, 1).c_str()) + 1;
            if (pairingDays <= 4) {
                for (auto it : ICPUtility::pairingConfigList) {
                    if (it->getBgnTerminal() == pairingDep && it->getEndTerminal() == pairingArr &&
                        it->getMaxPairingDays() < pairingDays) {
                        it->setMaxPairingDays(pairingDays);
                    }
                }
            }
        }

        lstDutyVoyage.push_back(lst[0].substr(1));
        lstPairingVoyage.push_back(lst[0]);
        for (size_t i = 1; i < lst.size(); i++) {
            if (lst[i - 1].substr(0, 1) != lst[i].substr(0, 1)) {
                string conn = pairingDep + "/" + lst[i - 1] + "/" + lst[i];
                ICPUtility::mapPairingRatio[conn] = ratio;
                lstDutyVoyage.push_back(lst[i].substr(1));
                lstPairingVoyage.push_back(lst[i]);
            } else {
                lstDutyVoyage.back() = lstDutyVoyage.back() + "-" + lst[i].substr(1);
                lstPairingVoyage.back() = lstPairingVoyage.back() + "-" + lst[i].substr(1);
            }
        }

        // 驻站的DUTY，按照我们的理解，业务只需要驻站的任务环稳定
        if (lstDutyVoyage.size() > 1) {
            for (auto dutyVoyage : lstDutyVoyage) {
                if (dutyVoyage.find("-") == string::npos)
                    continue;
                ICPUtility::lstDutyVoyageZhuZhan.push_back(dutyVoyage);
            }
        }
        if (lstPairingVoyage.size() > 1) {
            for (size_t i = 0; i < lstPairingVoyage.size(); i++) {
                string pairingVoyage;
                for (size_t j = 0; j <= i; j++) {
                    pairingVoyage += (pairingVoyage.empty() ? "" : "/") + lstPairingVoyage[j];
                }
                if (ICPUtility::mapPairingVoyageMultiDay.count(pairingVoyage)) {
                    ICPUtility::mapPairingVoyageMultiDay[pairingVoyage] =
                        max(ICPUtility::mapPairingVoyageMultiDay[pairingVoyage], ratio);
                } else {
                    ICPUtility::mapPairingVoyageMultiDay[pairingVoyage] = ratio;
                }
            }
        }
    }

    file.close();
}

void ICPIO::readSchLegList() {
    map<string, time_t> mapPairingDate;
    vector<SchLeg*> legList;
    int countTargetLeg = 0;

    time_t tmpDummyStartDate = makeTime(2100, 1, 1);
    time_t tmpDummyEndDate = makeTime(1900, 1, 1);

    string fileName = ICPUtility::INPUTPATH + string("sch_leg.csv");
    cout << "readSchLegList from file:" << fileName << endl;

    ifstream file(fileName.c_str());
    if (!file) {
        cout << "file " << fileName << " does not exist！" << endl;
        exit(0);
    }

    string buf;
    bool firstLine = true;
    while (getline(file, buf)) {
        if (firstLine) {
            firstLine = false;
            continue;
        }
        if (isUtf8(buf)) {
            buf = Utf8ToAnsi(buf);
        }
        if (buf.find("--") != string::npos)
            break;

        // 0-航班ID,1-航班号,2-发站,3-到站,4-STD,5-STA,6-承运人,7-执飞单位，8-机型，9-机型组,10-机号,11-国内国际,12-PORC,13-时长,14-航班性质(A/B/C/D),15-休息区等级(空/L1/L2/L3),16-置位航班所指正班的FLIGHT_ID，17-航班对应的任务环ID,
        // 18-FLIGHT_TYPE, 19-涉疆航线YN，20-航班历史（上周）所属基地串
        vector<string> subStrs = splitString(buf.c_str(), ",");
        if (subStrs.size() < 21) {
            continue;
        }
        time_t std = convertToDateTime(subStrs[4]);
        time_t flightDate = convertToDate(std - DAY_OFFSET_SECONED_DEFINE);
        string pairingId = subStrs[16];
        if (pairingId.empty())
            continue;

        // 同一任务环最早的航班日期作为任务环的日期
        if (mapPairingDate.count(pairingId) == 0) {
            mapPairingDate[pairingId] = flightDate;
        } else {
            mapPairingDate[pairingId] = min(mapPairingDate[pairingId], flightDate);
        }
    }
    file.close();

    // 回到文件头
    file.open(fileName.c_str());
    firstLine = true;
    while (getline(file, buf)) {
        if (firstLine) {
            firstLine = false;
            continue;
        }
        if (isUtf8(buf)) {
            buf = Utf8ToAnsi(buf);
        }

        if (buf.find("--") != string::npos)
            break;
        /* 0 - 航班ID,
         1-航班号,
         2-发站,
         3-到站,
         4-STD,
         5-STA,
         6-承运人,
         7-执飞单位，
         8-机型，
         9-机型组,
         10-机号,
         11-国内国际,
         12-P_OR_C,
         13-时长,
         14-航班性质(A/B/C/D),
         15-休息区等级(空/L1/L2/L3),
         16-置位航班所指正班的FLIGHT_ID,
         17-任务环ID,
         18-FLIGHT_TYPE,
         19-涉疆航线YN
         20-基地
         21-签到时间
         22-离场时间
         23-前车程
         24-后车程*/
        vector<string> subStrs = splitString(buf.c_str(), ",");
        if (subStrs.size() < 25) {
            continue;
        }
        string flightId = subStrs[0];
        string flightNo = subStrs[1];
        BasAirport* dep = _service->getAirport(subStrs[2]);
        if (dep == NULL) {
            cout << "Error: readSchLegList. Cannot find depAirport \"" << subStrs[2] << "\"" << endl;
            exit(0);
        }
        BasAirport* arr = _service->getAirport(subStrs[3]);
        if (arr == NULL) {
            cout << "Error: readSchLegList. Cannot find arrAirport \"" << subStrs[3] << "\"" << endl;
            exit(0);
        }
        time_t std = convertToDateTime(subStrs[4]);
        time_t sta = convertToDateTime(subStrs[5]);
        time_t flightDate = convertToDate(std - DAY_OFFSET_SECONED_DEFINE);
        if (flightDate < ICPUtility::bgnDate)
            continue;

        string carrier = subStrs[6];
        string crewOwner = subStrs[7];
        string acType = subStrs[8];
        string acTypeCrew = _service->getAcTypeCrew(acType); // subStrs[9];
        string acReg = subStrs[10];
        D_OR_I dori = D_OR_I::D;
        if (subStrs[11] == "I") {
            dori = D_OR_I::I;
        } else if (subStrs[11] == "R") {
            dori = D_OR_I::R;
        } else if (subStrs[11] == "T") {
            dori = D_OR_I::T;
        }
        P_OR_C porc = P_OR_C::P;
        if (subStrs[12] == "C") {
            porc = C;
        }
        int flyTime = atoi(subStrs[13].c_str()) * 60;
        // A-正常班、B-备份、C-本场、D-置位
        LEGTYPE legType = LEGTYPE::LEG_REGULAR;
        if (subStrs[14] == "A") {
            legType = LEGTYPE::LEG_REGULAR;
        } else if (subStrs[14] == "B") {
            legType = LEGTYPE::LEG_BACKUP;
        } else {
            continue;
        }
        REST_LEVEL restLevel = REST_LEVEL::REST_LEVEL_NIL;
        if (subStrs[15] == "L1") {
            restLevel = REST_LEVEL::REST_LEVEL_1;
        } else if (subStrs[15] == "L2") {
            restLevel = REST_LEVEL::REST_LEVEL_2;
        } else if (subStrs[15] == "L3") {
            restLevel = REST_LEVEL::REST_LEVEL_3;
        }
        string flightIdRef = subStrs[16];
        string pairingId = subStrs[17];
        // 训练航班和调机航班不组环
        if (subStrs[18] == "X" || subStrs[18] == "D")
            continue;
        bool isZWWW = (subStrs[19] == "Y");
        vector<string> bases = splitString(subStrs[20].c_str(), "/");
        bool isTarget = false;
        if (pairingId.empty()) {
            if (flightDate >= ICPUtility::bgnDate && flightDate <= ICPUtility::endDate) {
                isTarget = true;
            }
        } else if (mapPairingDate.count(pairingId) == 0) {
            if (flightDate >= ICPUtility::bgnDate && flightDate <= ICPUtility::endDate) {
                isTarget = true;
            }
        } else {
            if (mapPairingDate[pairingId] >= ICPUtility::bgnDate && mapPairingDate[pairingId] <= ICPUtility::endDate) {
                isTarget = true;
            }
        }
        SchLeg* newLeg = new SchLeg(legType, flightId, flightNo, dep, arr, std, sta, flightDate, acType, acTypeCrew,
                                    acReg, dori, porc, flyTime, restLevel, ICPUtility::filiale);
        time_t signIn = ICPUtility::signIn;
        time_t signOut = ICPUtility::signOut;
        time_t drivingIn = ICPUtility::drivingIn;
        time_t drivingOut = ICPUtility::drivingOut;
        if (!subStrs[21].empty() && isStringNumeric(subStrs[21])) {
            signIn = atoi(subStrs[21].c_str()) * 60;
        }
        if (!subStrs[22].empty() && isStringNumeric(subStrs[22])) {
            signOut = atoi(subStrs[22].c_str()) * 60;
        }
        if (!subStrs[23].empty() && isStringNumeric(subStrs[23])) {
            drivingIn = atoi(subStrs[23].c_str()) * 60;
        }
        if (!subStrs[24].empty() && isStringNumeric(subStrs[24])) {
            drivingOut = atoi(subStrs[24].c_str()) * 60;
        }
        newLeg->setSignIn(std - signIn);
        newLeg->setSignOut(sta + signOut);
        newLeg->setEndRestTime(std - drivingIn - signIn);
        newLeg->setBgnRestTime(sta + signOut + drivingOut);
        newLeg->setIsTarget(isTarget);
        newLeg->setIsZWWW(isZWWW);
        newLeg->setBaseList(bases);
        if (isTarget) {
            countTargetLeg++;
        }
        legList.push_back(newLeg);

        if (convertToDate(std) < tmpDummyStartDate) {
            tmpDummyStartDate = convertToDate(std);
        }
        if (convertToDate(std) > tmpDummyEndDate) {
            tmpDummyEndDate = convertToDate(std);
        }
    }
    file.close();

    ICPUtility::dummyBgnDate = max(tmpDummyStartDate, ICPUtility::dummyBgnDate);
    ICPUtility::dummyEndDate = min(tmpDummyEndDate, ICPUtility::dummyEndDate);

    vector<SchLeg*> legs;
    for (int i = 0; i < legList.size(); i++) {
        if (convertToDate(legList[i]->getStd()) >= ICPUtility::dummyBgnDate &&
            convertToDate(legList[i]->getStd()) <= ICPUtility::dummyEndDate) {
            legs.push_back(legList[i]);
        }
    }

    _service->setLegList(legs);
    _service->sortLegList();
    if (ICPUtility::isDebug) {
        cout << "total leg size is " << legs.size() << endl;
        cout << "target leg size is " << countTargetLeg << endl;
        for (int i = 0; i < legs.size(); i++) {
            if (ICPUtility::isDebug) {
                legs[i]->print();
            }
        }
    }
}

// 将临界点前面未闭环的任务环模拟成加机组，方便承接回程航班
void ICPIO::readPrevUnClosedPairingList() {
    int count = 0;
    vector<SchLeg*> legs;
    string fileName = ICPUtility::INPUTPATH + string("prev_unclosed_pairing.csv");
    cout << "readPrevUnClosedPairingList form file:" << fileName << endl;
    ifstream file(fileName.c_str());
    if (!file) {
        cout << "file " << fileName << " does not exist！" << endl;
        exit(0);
    }
    string buf;
    bool firstLine = true;
    while (getline(file, buf)) {
        if (firstLine) {
            firstLine = false;
            continue;
        }
        if (isUtf8(buf)) {
            buf = Utf8ToAnsi(buf);
        }

        /*PREV_UNCLOSED_PAIRING,START_TD,END_TA*/
        vector<string> subStrs = splitString(buf.c_str(), ",");
        if (subStrs.size() < 3)
            continue;
        vector<string> flts = splitString(subStrs[0].c_str(), "/");
        string firstFlt = flts.front();
        string lastFlt = flts.back();
        if (firstFlt.size() < 11 || lastFlt.size() < 11)
            continue;

        // PairingInfo
        auto lst = splitString(subStrs[0], "/");
        if (lst.empty())
            continue;

        string fltNo = lst[0];
        for (size_t i = 1; i < lst.size(); i++) {
            if (lst[i - 1].substr(0, 1) != lst[i].substr(0, 1)) {
                fltNo = fltNo + "/" + lst[i];
            } else {
                fltNo = fltNo + "-" + lst[i].substr(1);
            }
        }

        // 出发站
        string depCode3 = firstFlt.substr(firstFlt.size() - 6, 3);
        BasAirport* dep = _service->getAirport(depCode3);
        if (dep == NULL)
            continue;
        if (!dep->isBase())
            continue;

        // 达到站
        string arrCode3 = lastFlt.substr(lastFlt.size() - 3);
        BasAirport* arr = _service->getAirport(arrCode3);
        if (arr == NULL)
            continue;

        time_t std = convertToDateTime(subStrs[1]);
        time_t sta = convertToDateTime(subStrs[2]);
        auto leg = new SchLeg(LEG_REGULAR, "PREV_UNCLOSED_PAIRING" + to_string(count++), fltNo, dep, arr, std, sta,
                              ICPUtility::bgnDate - DAY_SECONED_DEFINE, "", "", "", D_OR_I::D, P_OR_C::P, 0,
                              REST_LEVEL_NIL, ICPUtility::filiale);
        leg->setSignIn(leg->getStd());
        leg->setSignOut(leg->getSta());
        leg->setEndRestTime(leg->getStd());
        leg->setBgnRestTime(leg->getSta());
        leg->setIsTarget(false);
        legs.push_back(leg);
    }
    _service->insertLegList(legs);
}

void ICPIO::readDeadHeadGrdList() {
    vector<SchLeg*> legList;
    string fileName = ICPUtility::INPUTPATH + string("deadhead_grd.csv");
    cout << "readDeadHeadGrdList form file:" << fileName << endl;
    ifstream file(fileName.c_str());
    if (!file) {
        cout << "file " << fileName << " does not exist！" << endl;
        exit(0);
    }
    string buf;
    bool firstLine = true;
    while (getline(file, buf)) {
        if (firstLine) {
            firstLine = false;
            continue;
        }
        if (isUtf8(buf)) {
            buf = Utf8ToAnsi(buf);
        }

        if (buf == "--")
            break;

        /*FLIGHT_ID, FLIGHT_NO, DEPA, ARRI, FLIGHT_DATE, STD,STA*/
        vector<string> subStrs = splitString(buf.c_str(), ",");
        if (subStrs.size() < 7) {
            continue;
        }

        string flightId = subStrs[0];
        string fltNo = subStrs[1];
        string depCode3 = subStrs[2];
        BasAirport* dep = _service->getAirport(depCode3);
        if (dep == NULL) {
            cout << "Warning: ICPIO::read bas_deadhead_grd. Cannot find depAirport \"" << depCode3 << "\"" << endl;
            continue;
        }
        string arrCode3 = subStrs[3];
        BasAirport* arr = _service->getAirport(arrCode3);
        if (arr == NULL) {
            cout << "Warning: ICPIO::read bas_deadhead_grd. Cannot find arrAirport \"" << arrCode3 << "\"" << endl;
            continue;
        }
        time_t theDate = convertToDate(subStrs[4]);
        time_t std = convertToDateTime(subStrs[5]);
        time_t sta = convertToDateTime(subStrs[6]);
        auto vbLeg = new SchLeg(LEG_VB, flightId, fltNo, dep, arr, std, sta, theDate, "", "", "", D_OR_I::D, P_OR_C::P,
                                0, REST_LEVEL_NIL, ICPUtility::filiale);
        vbLeg->setSignIn(vbLeg->getStd());
        vbLeg->setSignOut(vbLeg->getSta());
        vbLeg->setEndRestTime(vbLeg->getStd());
        vbLeg->setBgnRestTime(vbLeg->getSta());

        legList.push_back(vbLeg);
    }
    file.close();

    _service->insertLegList(legList);
    for (int i = 0; i < legList.size(); i++) {
        if (ICPUtility::isDebug) {
            legList[i]->print();
        }
    }
    if (ICPUtility::isDebug) {
        cout << "# bus leg is " << legList.size() << endl;
    }
}

void ICPIO::readDeadHeadElfList() {
    vector<SchLeg*> legList;
    int idx = 0;
    string fltId, fltNo;
    time_t theDate, std, sta;
    SchLeg* vbLeg;
    for (auto airport1 : _service->getAirportList()) {
        if (!airport1->isBase())
            continue;
        for (auto airport2 : _service->getAirportList()) {
            if (airport2->isBase())
                continue;
            if (!airport2->fsbOvernight())
                continue;
            if (airport2->getDorI() != D_OR_I::D)
                continue;

            theDate = ICPUtility::bgnDate;
            while (theDate <= ICPUtility::endDate) {
                // 去程(基地->过夜机场)
                idx++;
                fltId = "ELF" + to_string(idx);
                fltNo = "VB" + to_string(idx);
                std = theDate;
                sta = std + 1;
                vbLeg = new SchLeg(LEG_VB, fltId, fltNo, airport1, airport2, std, sta, theDate, "", "", "ELF",
                                   D_OR_I::D, P_OR_C::P, 0, REST_LEVEL_NIL, ICPUtility::filiale);
                vbLeg->setSignIn(vbLeg->getStd());
                vbLeg->setSignOut(vbLeg->getSta());
                vbLeg->setEndRestTime(vbLeg->getStd());
                vbLeg->setBgnRestTime(vbLeg->getSta());
                legList.push_back(vbLeg);
                // 回程(过夜机场->基地)
                idx++;
                fltId = "ELF" + to_string(idx);
                fltNo = "VB" + to_string(idx);
                std = theDate + DAY_SECONED_DEFINE - 1;
                sta = std + 1;
                vbLeg = new SchLeg(LEG_VB, fltId, fltNo, airport2, airport1, std, sta, theDate, "", "", "ELF",
                                   D_OR_I::D, P_OR_C::P, 0, REST_LEVEL_NIL, ICPUtility::filiale);
                vbLeg->setSignIn(vbLeg->getStd());
                vbLeg->setSignOut(vbLeg->getSta());
                vbLeg->setEndRestTime(vbLeg->getStd());
                vbLeg->setBgnRestTime(vbLeg->getSta());
                legList.push_back(vbLeg);

                theDate = theDate + DAY_SECONED_DEFINE;
            }
        }
    }
    _service->insertLegList(legList);
}

void ICPIO::readDeadHeadAirList() {
    vector<SchLeg*> legList;
    string fileName = ICPUtility::INPUTPATH + string("deadhead_air.csv");
    cout << "readBasDeadHeadAirList form file:" << fileName << endl;
    ifstream file(fileName.c_str());
    if (!file) {
        cout << "file " << fileName << " does not exist！" << endl;
        exit(0);
    }
    string buf;
    bool firstLine = true;
    while (getline(file, buf)) {
        if (firstLine) {
            firstLine = false;
            continue;
        }
        if (isUtf8(buf)) {
            buf = Utf8ToAnsi(buf);
        }

        if (buf.find("--") != string::npos) {
            break;
        }

        // 0-航班ID,1-航班号,2-发站,3-到站,4-STD,5-STA,6-承运人,7-执飞单位，8-机型，9-机型组,10-机号,11-国内国际
        vector<string> subStrs = splitString(buf.c_str(), ",");
        if (subStrs.size() < 12)
            continue;

        string flightId = subStrs[0];
        string fltNo = subStrs[1];
        string depCode3 = subStrs[2];
        BasAirport* dep = _service->getAirport(depCode3);
        if (dep == NULL)
            continue;
        string arrCode3 = subStrs[3];
        BasAirport* arr = _service->getAirport(arrCode3);
        if (arr == NULL)
            continue;
        time_t std = convertToDateTime(subStrs[4]);
        time_t sta = convertToDateTime(subStrs[5]);
        time_t theDate = convertToDate(std - DAY_OFFSET_SECONED_DEFINE);
        string carrier = subStrs[6];
        string crewOwner = subStrs[7];
        string acType = subStrs[8];
        string acTypeCrew = subStrs[9];
        string acReg = subStrs[10];
        D_OR_I dori = D_OR_I::D;
        if (subStrs[11] == "I") {
            dori = D_OR_I::I;
        } else if (subStrs[11] == "R") {
            dori = D_OR_I::R;
        } else if (subStrs[11] == "T") {
            dori = D_OR_I::T;
        }
        // 国际班不参与置位
        if (dori != D_OR_I::D)
            continue;

        SchLeg* vaLeg = new SchLeg(LEG_VA, flightId, fltNo, dep, arr, std, sta, theDate, acType, acTypeCrew, acReg,
                                   dori, P_OR_C::P, 0, REST_LEVEL_NIL, crewOwner);

        time_t signIn = ICPUtility::signIn;
        time_t signOut = ICPUtility::signOut;
        time_t drivingIn = ICPUtility::drivingIn;
        time_t drivingOut = ICPUtility::drivingOut;
        string key1 = acTypeCrew + dep->getCode3() + arr->getCode3();
        if (ICPUtility::mapAirportConfig.count(key1) > 0) {
            signIn = ICPUtility::mapAirportConfig[key1].signIn;
            signOut = ICPUtility::mapAirportConfig[key1].signout;
            drivingIn = ICPUtility::mapAirportConfig[key1].drivingIn;
            drivingOut = ICPUtility::mapAirportConfig[key1].drivingOut;
        } else {
            string key2 = acTypeCrew + dep->getCode3();
            if (ICPUtility::mapAirportConfig.count(key2) > 0) {
                signIn = ICPUtility::mapAirportConfig[key2].signIn;
                drivingIn = ICPUtility::mapAirportConfig[key2].drivingIn;
            }

            string key3 = acTypeCrew + arr->getCode3();
            if (ICPUtility::mapAirportConfig.count(key3) > 0) {
                signOut = ICPUtility::mapAirportConfig[key3].signout;
                drivingOut = ICPUtility::mapAirportConfig[key3].drivingOut;
            }
        }
        vaLeg->setSignIn(std - signIn);
        vaLeg->setSignOut(sta + signOut);
        vaLeg->setEndRestTime(std - drivingIn - signIn);
        vaLeg->setBgnRestTime(sta + signOut + drivingOut);
        legList.push_back(vaLeg);
    }
    file.close();
    _service->insertLegList(legList);

    for (int i = 0; i < legList.size(); i++) {
        // legList[i]->print();
    }

    cout << "# deadhead air leg is " << legList.size() << endl;
}

void ICPIO::readBestAirlineList() {
    vector<string> lstBestAirline;

    string buf;
    string fileName = ICPUtility::INPUTPATH + string("best_airline.csv");
    cout << "readBestAirlineList from file " << fileName << "！" << endl;
    ifstream file(fileName.c_str());
    if (!file) {
        cout << "file " << fileName << " does not exist！" << endl;
        exit(0);
    }

    bool firstLine = true;
    while (getline(file, buf)) {
        if (firstLine) {
            firstLine = false;
            continue;
        }
        if (isUtf8(buf)) {
            buf = Utf8ToAnsi(buf);
        }
        vector<string> subStrs = splitString(buf.c_str(), ",");
        if (subStrs.size() < 3) {
            continue;
        }
        string dep = subStrs[0];
        string arr = subStrs[1];
        string flightCom = subStrs[2];
        for (auto flightNo : splitString(subStrs[2].c_str(), "/")) {
            if (flightNo.length() < 5)
                continue;
            lstBestAirline.push_back(flightNo.substr(2) + dep + arr);
        }
    }

    file.close();
    for (auto leg : _service->getLegList()) {
        leg->setBestAirline(false);
        if (leg->getLegType() != LEG_REGULAR)
            continue;
        string key = leg->getFlightNo() + leg->getDep()->getCode3() + leg->getArr()->getCode3();
        auto iter = find(lstBestAirline.begin(), lstBestAirline.end(), key);
        if (iter != lstBestAirline.end()) {
            leg->setBestAirline(true);
        }
    }
}

void ICPIO::readSchConfigB() {
    string buf;
    string fileName = ICPUtility::INPUTPATH + string("sch_config_b.csv");
    cout << "readSchConfigB from file " << fileName << "！" << endl;
    ifstream file(fileName.c_str());
    if (!file) {
        cout << "file " << fileName << " does not exist！" << endl;
        exit(0);
    }

    bool firstLine = true;
    while (getline(file, buf)) {
        if (firstLine) {
            firstLine = false;
            continue;
        }
        if (isUtf8(buf)) {
            buf = Utf8ToAnsi(buf);
        }
        if (buf.find("--") != string::npos) {
            break;
        }
        // BASE,AC_TYPES,CREW_ID
        vector<string> subStrs = splitString(buf.c_str(), ",");
        if (subStrs.size() < 3) {
            continue;
        }

        string base = subStrs[0];
        string acTypes = subStrs[1];
        if (!isStringNumeric(subStrs[2])) {
            continue;
        }
        int crewId = atoi(subStrs[2].c_str());

        ICPUtility::lstSchConfigB.push_back(new SchConfigB(base, acTypes, crewId));
    }

    file.close();
}

void ICPIO::readHrCrew() {
    string buf;
    string fileName = ICPUtility::INPUTPATH + string("hr_crew.csv");
    cout << "readHrCrew from file " << fileName << "！" << endl;
    ifstream file(fileName.c_str());
    if (!file) {
        cout << "file " << fileName << " does not exist！" << endl;
        exit(0);
    }

    bool firstLine = true;
    while (getline(file, buf)) {
        if (firstLine) {
            firstLine = false;
            continue;
        }
        if (isUtf8(buf)) {
            buf = Utf8ToAnsi(buf);
        }
        if (buf.find("--") != string::npos)
            break;
        // P_CODE,BASE
        vector<string> subStrs = splitString(buf.c_str(), ",");
        if (subStrs.size() < 2) {
            continue;
        }
        HrCrew* hrCrew = new HrCrew(subStrs[0], subStrs[1]);
        _service->pushHrCrew(hrCrew);
    }

    file.close();
}

void ICPIO::readTechInfo() {
    string buf;
    string fileName = ICPUtility::INPUTPATH + string("tech_info.csv");
    cout << "readTechInfo from file " << fileName << "！" << endl;
    ifstream file(fileName.c_str());
    if (!file) {
        cout << "file " << fileName << " does not exist！" << endl;
        exit(0);
    }

    bool firstLine = true;
    while (getline(file, buf)) {
        if (firstLine) {
            firstLine = false;
            continue;
        }
        if (isUtf8(buf)) {
            buf = Utf8ToAnsi(buf);
        }
        if (buf.find("--") != string::npos)
            break;
        // P_CODE,AC_TYPE_CREW,TECH_NO
        vector<string> subStrs = splitString(buf.c_str(), ",");
        if (subStrs.size() < 3) {
            continue;
        }
        string pcode = subStrs[0];
        string acTypeCrew = subStrs[1];
        string techNo = subStrs[2];
        HrCrew* hrCrew = _service->getHrCrew(pcode);
        if (hrCrew == NULL)
            continue;
        personTechInfo techInfo;
        techInfo.acTypeCrew = acTypeCrew;
        techInfo.techNo = techNo;
        hrCrew->pushPersonTechInfo(techInfo);
    }

    file.close();
}

void ICPIO::readPersonSchedule() {
    string buf;
    string fileName = ICPUtility::INPUTPATH + string("person_schedule.csv");
    cout << "readPersonSchedule from file " << fileName << "！" << endl;
    ifstream file(fileName.c_str());
    if (!file) {
        cout << "file " << fileName << " does not exist！" << endl;
        exit(0);
    }

    bool firstLine = true;
    while (getline(file, buf)) {
        if (firstLine) {
            firstLine = false;
            continue;
        }
        if (isUtf8(buf)) {
            buf = Utf8ToAnsi(buf);
        }
        if (buf.find("--") != string::npos)
            break;
        // P_CODE,FROM_DATE, TO_DATE, FLIGHT_TYPE, FLIGHT_COM
        vector<string> subStrs = splitString(buf.c_str(), ",");
        if (subStrs.size() < 5) {
            continue;
        }
        string pcode = subStrs[0];
        HrCrew* hrCrew = _service->getHrCrew(pcode);
        if (hrCrew == NULL)
            continue;
        personSchedule sch;
        sch.fromDate = convertToDateTime(subStrs[1]);
        sch.toDate = convertToDateTime(subStrs[2]);
        sch.flightType = subStrs[3];
        sch.flightCom = subStrs[4];
        hrCrew->pushPersonSchedule(sch);
    }

    file.close();
}

void ICPIO::writeSln(vector<SchPairing*> pairingList) {
    vector<SchPairing*> pairings;
    for (size_t i = 0; i < pairingList.size(); i++) {
        if (pairingList[i]->getDepDate() > ICPUtility::endDate - DAY_SECONED_DEFINE)
            continue;
        pairings.push_back(pairingList[i]);
    }
    writeSlnPairingList(pairings, "pairing");

    vector<SchLeg*> vbLegs;
    for (int i = 0; i < pairings.size(); i++) {
        vector<SchLeg*> legs = pairings[i]->getLegList();
        for (int j = 0; j < legs.size(); j++) {
            if (legs[j]->getAcReg() == "ELF")
                continue;
            if (legs[j]->getLegType() != LEG_VB)
                continue;

            vbLegs.push_back(legs[j]);
        }
    }

    writeSlnVBList(vbLegs, "deadhead_car");
}

void ICPIO::writeSlnPairingList(vector<SchPairing*> pairingList, string fName) {
    string fname = ICPUtility::OUTPUTPATH + fName + ".csv";
    // 如果文件存在的话，先删除文件
    FILE* file1 = fopen(fname.c_str(), "r");
    if (file1 != NULL) {
        fclose(file1);
        remove(fname.c_str());
    }

    fstream file;
    file.open(fname, ios::app);
    cout << "write file path is " << fname << endl;

    file << "PAIRING_ID,PAIRING_INFO,CREW_ID,BASE" << endl;
    int countDeadheadId = 10000;
    for (int i = 0; i < pairingList.size(); i++) {
        pairingList[i]->genCrewId();
        int crewId = pairingList[i]->getCrewId();
        string base = pairingList[i]->getBase();

        file << i + 10000000 << ",";
        auto dutys = pairingList[i]->getDutyList();
        for (int j = 0; j < dutys.size(); j++) {
            if (j != 0) {
                file << "/";
            }
            vector<SchLeg*> legs = dutys[j]->getLegList();
            string flightIds;
            for (int k = 0; k < legs.size(); k++) {
                if (legs[k]->getFlightId().find("PREV") != string::npos)
                    continue;
                if (legs[k]->getAcReg() == "ELF")
                    continue;
                if (legs[k]->isDeadHead() && legs[k]->getDate() < ICPUtility::bgnDate)
                    continue;

                if (legs[k]->getLegType() == LEG_VB) {
                    flightIds += flightIds.empty() ? "" : "#";
                    flightIds += "VB" + to_string(countDeadheadId);
                    countDeadheadId++;
                } else if (legs[k]->getLegType() == LEG_VA) {
                    flightIds += flightIds.empty() ? "" : "#";
                    flightIds += "VA" + legs[k]->getFlightId();
                } else if (legs[k]->getLegType() == LEG_BACKUP) {
                    flightIds += flightIds.empty() ? "" : "#";
                    flightIds += legs[k]->getFlightId();
                } else if (legs[k]->isTarget() == false && legs[k]->getStd() < ICPUtility::endDate) {
                    flightIds += flightIds.empty() ? "" : "#";
                    flightIds += "VA" + legs[k]->getFlightId();
                } else {
                    flightIds += flightIds.empty() ? "" : "#";
                    flightIds += legs[k]->getFlightId();
                }
            }
            file << flightIds;
        }
        file << "," << crewId << "," << base << endl;
    }
    file.close();
}

void ICPIO::writeSlnVBList(vector<SchLeg*> legBusList, string fName) {
    string fname = ICPUtility::OUTPUTPATH + fName + ".csv";
    // 如果文件存在的话，先删除文件
    FILE* file1 = fopen(fname.c_str(), "r");
    if (file1 != NULL) {
        fclose(file1);
        remove(fname.c_str());
    }

    fstream file;
    file.open(fname, ios::app);
    cout << "write file path is " << fname << endl;

    file << "DEADHEAD_ID,DEP,ARR,STD,STA" << endl;
    int countDeadheadId = 10000;
    for (int i = 0; i < legBusList.size(); i++) {
        file << "VB" << countDeadheadId << "," << legBusList[i]->getDep()->getCode3() << ","
             << legBusList[i]->getArr()->getCode3() << "," << getTimeStr(legBusList[i]->getStd()) << ","
             << getTimeStr(legBusList[i]->getSta()) << endl;
        countDeadheadId++;
    }

    file.close();
}

void ICPIO::readVBList() {
    vector<SchLeg*> deadheadLegs;

    string filename = ICPUtility::INPUTPATH + string("bas_deadhead_grd.csv");
    cout << "readVBList from file:" << filename << endl;
    ifstream file(filename.c_str());

    string buf;
    while (getline(file, buf)) {
        vector<string> subStrs = splitString(buf.c_str(), ",");
        if (subStrs.size() < 2) {
            continue;
        }

        string id = subStrs[0]; // deadhead id
        // 对应的航班ID没有
        BasAirport* depAirport = _service->getAirport(subStrs[3]);
        BasAirport* arrAirport = _service->getAirport(subStrs[4]);
        time_t depTime = convertToDateTime(subStrs[5]);
        time_t arrTime = convertToDateTime(subStrs[6]);
        time_t date = convertToDate(depTime);

        SchLeg* newLeg = new SchLeg(LEG_VB, id, "BUS" + id, depAirport, arrAirport, depTime, arrTime, date, "", "", "",
                                    D_OR_I::D, P_OR_C::P, 0, REST_LEVEL_NIL, ICPUtility::filiale);
        deadheadLegs.push_back(newLeg);
    }

    file.close();
    _service->setSlnDeadheadLeglist(deadheadLegs);
}

void ICPIO::readPairingList() {
    vector<SchPairing*> pairings;

    string filename = ICPUtility::INPUTPATH + string("pairing.csv");
    cout << "* Read soln_pairing form file:" << filename << endl;
    ifstream file(filename.c_str());

    string buf;
    while (getline(file, buf)) {
        vector<string> subStrs = splitString(buf.c_str(), ",");
        if (subStrs.size() < 3) {
            continue;
        }
        // pairing id
        string name = subStrs[0];
        // legs
        vector<string> fltIds = splitString(subStrs[1], "#");
        vector<SchLeg*> curLegs;
        for (auto& fltId : fltIds) {
            SchLeg* curLeg = NULL;
            SchLeg* dLeg = NULL;
            SchLeg* rLeg = NULL;
            if (fltId.find("VA") == string::npos) {
                rLeg = _service->getLeg(fltId);
            } else {
                fltId = fltId.substr(2);
                rLeg = _service->getLeg(fltId);
                dLeg = _service->newVALeg(rLeg);
            }

            if (dLeg != NULL) {
                curLegs.push_back(dLeg);
            } else if (rLeg != NULL) {
                curLegs.push_back(rLeg);
            } else {
                cout << "Error: readPairingList. Cannot find leg " << fltId << endl;
                exit(0);
            }
        }
        string baseCode = subStrs[2];
        SchPairing* newPairing = _service->convertPairing(name, curLegs, baseCode);
        newPairing->setName(name);
        pairings.push_back(newPairing);
    }
    file.close();

    _service->setSlnPairingList(pairings);
}
